package cn.datastruct.test;
/*
    实现计数器思路：
        1、定义两个栈，一个用来存取数字，一个用来存取操作符
        2、读取的是数字入栈，操作符则当前的栈顶元素比较优先级（人为定义），如果优先级大于则入栈，栈空也入栈。
        反之则操作符栈弹出当前元素，数据栈弹出两个数字进行计算。当所有的字符都进栈了，就开开始弹出，
        数据栈弹出两个数，操作符栈弹出一个运算符进行运算，直至最有最有一个数据，将其存入栈，最后一个数就是结果
        如果是左括号则入栈，右括号出栈
        3、函数
            3.1、boolean recognize(char ch)区别是数字还是操作符
            3.2、int priority(char ch)
            3.3、int operateNum(int num1, int num2, char ch)
* */


import java.util.Scanner;
import java.util.Stack;

public class CalculatorDemo {
    //boolean recognize(char ch)区别是数字还是操作符
    public static boolean recognize(char ch) {
        return ch == '*' || ch == '+' || ch == '-' || ch == '/';
    }

    //int priority(char ch)
    public static int priority(char ch) {
        int pri = 0;
        switch (ch) {
            case '+':
                pri = 1;
                break;
            case '-':
                pri = 1;
                break;
            case '*':
                pri = 2;
                break;
            case '/':
                pri = 2;
                break;
            default:
                System.out.println("无法识别符号");
        }
        //返零表示栈为空
        return pri;
    }

    public static int operateNum(int num1, int num2, char ch) {
        int res = 0;
        switch (ch) {
            case '+':
                res = num1 + num2;
                break;
            case '-':
                res = num1 - num2;
                break;
            case '*':
                res = num1 * num2;
                break;
            case '/':
                res = num1 / num2;
                break;
            default:
                System.out.println("无法识别符号");
        }
        return res;
    }


    public static void main(String[] args) {
        Stack<String> valueStack = new Stack<String>();
        Stack<Character> operateStack = new Stack<Character>();

        //输入字符串
//        Scanner sc = new Scanner(System.in);
//        String s = sc.nextLine();
        String s = "(1+3)-(2)-2-10+100*3-10/2";
        String str = "";//用来拼接多位数
        int length = s.length();
        char ch = '0';

        //将数字和操作符添加栈
        for (int i = 0; i < length; i++) {
            ch = s.charAt(i);
            //分析当前运算符级别
            if (recognize(ch)) {
                if (str.length() != 0) {
                    valueStack.push(str);
                    str = "";
                }
                if (operateStack.empty() || operateStack.peek() == '(') {//符号栈为空这入栈,或优先级小于当前符号优先级
                    operateStack.push(ch);
                } else if (priority(operateStack.peek()) >= priority(ch)) {//当符号优先级大于等于待入栈符号优先级
                    do {
                        int num2 = Integer.parseInt(valueStack.pop());
                        int num1 = Integer.parseInt(valueStack.pop());
                        valueStack.push(String.valueOf(operateNum(num1, num2, operateStack.pop())));
                    }
                    while (operateStack.size() > 0 && priority(operateStack.peek()) >= priority(ch));
                    operateStack.push(ch);
                } else if (priority(operateStack.peek()) < priority(ch)) {
                    operateStack.push(ch);
                }
            } else if (ch == '(') {//左括号入栈
                operateStack.push(ch);
            } else if (ch == ')') {//右括号出栈
                valueStack.push(str);
                str = "";
                while (operateStack.peek() != '(') {
                    int num2 = Integer.parseInt(valueStack.pop());
                    int num1 = Integer.parseInt(valueStack.pop());
                    valueStack.push(String.valueOf(operateNum(num1, num2, operateStack.pop())));
                }
                operateStack.pop();//将左括号弹出
            } else {
                //多位数拼接
                str += ch;
            }

        }
        //最后一个数填入,判断算术是不是以括号结尾
        if (ch != ')')
            valueStack.push(str);

        //栈中元素进行运算
        while (operateStack.size() > 0) {
            int num2 = Integer.parseInt(valueStack.pop());
            int num1 = Integer.parseInt(valueStack.pop());
            valueStack.push(String.valueOf(operateNum(num1, num2, operateStack.pop())));
        }

        System.out.println("操作栈的个数=" + operateStack.size());
        System.out.println("-------------------");
        System.out.println("数据栈的个数=" + valueStack.size());
        System.out.printf("%s=%s", s, valueStack.pop());

    }
}
